package com.coolgor.airvow.SQL;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.*;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import com.coolgor.airvow.File.FileIO;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;


public class DataSourceManager implements Serializable {
	
	private static DataSourceManager instance; //数据源的实例 
	
	private static String configure_file = "database.configuration"; //默认的数据源配置文件
	
	private Map DataSourceList = new HashMap(); 
	
	private Vector configureList = new Vector(); 
	
	
    public DataSourceManager(){}
    
    public DataSourceManager(String configure_file){
		//获取当前操作系统路径的斜杠符号 若是win系统，则为“\” 若是linux系统，则为“/”
		String seperator = System.getProperty("file.separator");
		List<String> pathList = new ArrayList<String>();
		pathList.add("");
		//获取项目路径
		File f = new File("");
		String filePath = null;
		try {
			filePath = f.getCanonicalPath();
		} catch (IOException e) {
			e.printStackTrace();
		}
		filePath = filePath.replace("/", seperator) + seperator;
		pathList.add(filePath);
		pathList.add(filePath + "resources" + seperator);
		pathList.add(filePath + "configuration" + seperator);
		//获取classpath路径
		filePath = this.getClass().getResource("/").getPath().replace("/", seperator);
		pathList.add(filePath);
		pathList.add(filePath + "resources" + seperator);
		pathList.add(filePath + "configuration" + seperator);
		//循环检索文件是否存在
		File file ;
		for (int i=0;i<pathList.size();i++){
			file = new File(pathList.get(i) + configure_file);
			if ((file.exists())) {
				DataSourceManager.configure_file = pathList.get(i) + configure_file;
				break;
			}
		}
    	System.out.println("|>Configure_File: " + DataSourceManager.configure_file);
    }
    
    private void init() {
    	System.out.println("Initializing all DataSources ...... ");
    	this.configureList = readConfigure();
    	DataSourceList.clear();
    	DataBaseConfigure info ;
    	DataSource ds ;
    	for(int i=0;i<configureList.size();i++){
    		info = (DataBaseConfigure) configureList.elementAt(i);
    		ds = DataSourceFactory.create(info);
    		DataSourceList.put(info.name, ds);
    	}
    	System.out.println("Complete initialize all DataSources ! ");
    }
    
    private Vector readConfigure() {
    	Vector list = new Vector(); 
		//为解析XML作准备，创建DocumentBuilderFactory实例,指定DocumentBuilder
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = null;
		try {
			db = dbf.newDocumentBuilder();
		} catch (ParserConfigurationException pce) {
			System.err.println(pce); //出异常时输出异常信息，然后退出，下同
			System.exit(1);
		}

		Document doc = null;
		try {
			doc = db.parse(configure_file);
		} catch (DOMException dom) {
			System.err.println(dom.getMessage());
			System.exit(1);
		} catch (IOException ioe) {
			System.err.println(ioe);
			System.exit(1);
		} catch (SAXException saxe) {
			System.err.println(saxe);
			System.exit(1);
		}
		//一下是解析XML过程，先取根元素
		Element root = doc.getDocumentElement();
		//取"database"元素列表
		NodeList databases = root.getElementsByTagName("DataBase");
		for (int i = 0; i < databases.getLength(); i++) {
			//依次取每个"database"元素
			Element database = (Element) databases.item(i);
			//创建一个数据库配置信息的实例
			DataBaseConfigure info = new DataBaseConfigure();
			//取数据库配置名称属性
			info.name = database.getAttribute("name");
			//取dbtype元素，下面类同
			NodeList dbtype = database.getElementsByTagName("dbtype");
			if (dbtype.getLength() == 1) {
				Element e = (Element) dbtype.item(0);
				Text t = (Text) e.getFirstChild();
				info.dbtype = t.getNodeValue();
			}
			NodeList dbdriver = database.getElementsByTagName("dbdriver");
			if (dbdriver.getLength() == 1) {
				Element e = (Element) dbdriver.item(0);
				Text t = (Text) e.getFirstChild();
				info.dbdriver = t.getNodeValue();
			}
			NodeList url = database.getElementsByTagName("url");
			if (url.getLength() == 1) {
				Element e = (Element) url.item(0);
				Text t = (Text) e.getFirstChild();
				info.url = t.getNodeValue();
			}
			NodeList ip = database.getElementsByTagName("ip");
			if (ip.getLength() == 1) {
				Element e = (Element) ip.item(0);
				Text t = (Text) e.getFirstChild();
				info.ip = t.getNodeValue();
			}
			NodeList port = database.getElementsByTagName("port");
			if (port.getLength() == 1) {
				Element e = (Element) port.item(0);
				Text t = (Text) e.getFirstChild();
				info.port = t.getNodeValue();
			}
			NodeList sid = database.getElementsByTagName("sid");
			if (sid.getLength() == 1) {
				Element e = (Element) sid.item(0);
				Text t = (Text) e.getFirstChild();
				info.sid = t.getNodeValue();
			}
			NodeList dbname = database.getElementsByTagName("dbname");
			if (dbname.getLength() == 1) {
				Element e = (Element) dbname.item(0);
				Text t = (Text) e.getFirstChild();
				info.dbname = t.getNodeValue();
			}
			NodeList username = database.getElementsByTagName("username");
			if (username.getLength() == 1) {
				Element e = (Element) username.item(0);
				Text t = (Text) e.getFirstChild();
				info.username = t.getNodeValue();
			}
			NodeList password = database.getElementsByTagName("password");
			if (password.getLength() == 1) {
				Element e = (Element) password.item(0);
				Text t = (Text) e.getFirstChild();
				info.password = t.getNodeValue();
			}
			NodeList maxconn = database.getElementsByTagName("maxconn");
			if (maxconn.getLength() == 1) {
				Element e = (Element) maxconn.item(0);
				Text t = (Text) e.getFirstChild();
				info.maxconnection = t.getNodeValue();
			}	
			list.add(info);
		}
    	return list;
    }
	
    /**
     * 获得连接
     * @throws SQLException 
     */
	public static synchronized Connection getConnection(String name) throws SQLException{   
		if   (instance   ==   null) {   
			instance   =   new DataSourceManager(configure_file);   
			instance.init();   
		}  
		Connection c;
		try {
			c = instance.getConn(name);
		} catch (SQLException sqlEx) {
			System.err.println("DataSourceManager.getConnection() - 从数据源DataSource中获取连接时出现异常 " );  
			throw sqlEx;
		}
		return c;   
	}  
	
    /**
     * 实例获得连接
     * @throws SQLException 
     */
	private Connection getConn(String name) throws SQLException {
		DataSource ds = (DataSource) instance.DataSourceList.get(name);
		if ( null == ds ){
			System.out.println("  <"+name+"> is not exist !" );
			return null;
		}
		Connection con = null;
		try {
			con = ds.getConnection();
		} catch (SQLException sqlEx) {
//			System.out.println(this.getClass().getName() + ".getConn() - 从数据源DataSource中获取连接时出现异常: " + sqlEx.toString()); 
			System.err.println(this.getClass().getName() + ".getConn() - 从数据源DataSource中获取连接时出现异常 " );  
			throw sqlEx;
			//sqlEx.printStackTrace();
		}
//		int step=10;		
//		while(null==con && step>0){
//			for (long i=0;i<99999999;i++);
//			con = ds.getConnection();
//			step--;
//		}
		instance.DataSourceList.put(name, ds);
		try{
			if ( null == con ) {
				System.err.println("---- Get a connection from <"+name+"> : Connection is NULL !");
				System.err.println("-------- Maybe there are not enough connection to assign ! Try to add the max number of connection !");
			} else if (con.isClosed()) {
				System.err.println("---- Get a connection from <"+name+"> : Connection is closed !");
			}
//			else
//				System.out.println("---- Get a connection from <"+name+"> : Success !");
		}catch (SQLException e){
			System.err.println("---- Get a connection from <"+name+"> : SQLException !");		
		}
		return con;
	}  
	 
	/**   
    *   释放连接   
    */ 
	public static synchronized void freeConnection(String name,Connection con) {
		if (instance == null) {   
			instance = new DataSourceManager(configure_file);   
			instance.init();   
		}  
		instance.freeConn(name,con);   
	}   
	    
	/**   
	*    实例释放连接   
	*/   
	private void freeConn(String name,Connection con){
		DataSource ds = (DataSource) instance.DataSourceList.get(name);
		if (ds == null ){
			System.err.println("  <"+name+"> is not exist !" );
		}else{
//			System.out.println("---- free a connection to <"+name+"> : Success !");
			ds.freeConnection(con);
			instance.DataSourceList.put(name, ds);
		}
	}  
	
	  /**   
	    *   释放所有   
	 * @throws SQLException 
	    */  
	public void release() throws SQLException {
		System.out.println("Releasing all DataSources ...... ");
		Iterator iterator=instance.DataSourceList.keySet().iterator(); 
		DataSource ds;
		while(iterator.hasNext()){ 
			Object key = iterator.next(); 
			ds = (DataSource) instance.DataSourceList.get(key);
			try {
				ds.release();
			} catch (SQLException sqlEx) {
				System.err.println(this.getClass().getName() + ".release() - 从 数据源管理器 中释放连接时出现异常 " );  
				throw sqlEx;
			}
		} 
		instance.DataSourceList.clear();
    	System.out.println("Complete release all DataSources ! ");
	}
	        
}
